package com.fc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fc.constant.FieldConstant;
import com.fc.context.BaseContext;
import com.fc.dto.UserDTO;
import com.fc.dto.UserLoginDTO;
import com.fc.dto.UserRegisterDTO;
import com.fc.entity.User;
import com.fc.exception.BaseException;
import com.fc.exception.LoginException;
import com.fc.exception.RegisterException;
import com.fc.mapper.UserMapper;
import com.fc.properties.JwtProperties;
import com.fc.service.IUserService;
import com.fc.utils.AuthUtil;
import com.fc.utils.CaptchaImageUtil;
import com.fc.utils.JwtUtil;
import com.fc.vo.UserLoginVO;
import com.fc.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    @Qualifier("objectRedisTemplate")
    private RedisTemplate<String, Object> objectRedisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserLoginVO login(UserLoginDTO userLoginDTO) {
        //先校验验证码是否正确
        if (!verifyCaptcha(userLoginDTO.getUuid(), userLoginDTO.getCode())) {
            throw new LoginException("验证码错误");
        }
        //两种登录方式
        String identifier;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (userLoginDTO.getUsername() != null && !userLoginDTO.getUsername().isEmpty()) {
            String username = userLoginDTO.getUsername();
            queryWrapper.eq(FieldConstant.USERNAME, username);//用户名+密码
            identifier = username;
        } else if ((userLoginDTO.getPhoneNumber() != null && !userLoginDTO.getPhoneNumber().isEmpty())) {
            String phoneNumber = userLoginDTO.getPhoneNumber();
            queryWrapper.eq(FieldConstant.PHONE_NAME, phoneNumber);//手机号＋密码
            identifier = phoneNumber;
        } else {
            throw new LoginException("参数异常");
        }
        //查询数据库是否有该用户
        User user = getOne(queryWrapper);
        if (user == null) {
            throw new LoginException("没有该用户");
        }
        // 进行身份验证
        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(identifier, userLoginDTO.getPassword()));

        // 更新最后登录时间
        user.setLastLogin(LocalDateTime.now());
        updateById(user);

        // 生成 JWT 令牌
        Long userId = user.getId();
        Long roleId = userMapper.selectRoleIdByUserId(userId);
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        String token = JwtUtil.createJWT(jwtProperties.getSecretKey(), jwtProperties.getTtl(), claims);
        return UserLoginVO.builder().userId(userId).roleId(roleId).token(token).build();
    }

    @Override
    public void logout(HttpServletRequest request) {
        String token = request.getHeader("token");
        objectRedisTemplate.opsForValue().set(token, token, 30, TimeUnit.MINUTES);
    }

    /**
     * 生成验证码并存储code到redis，返回base64图片
     *
     * @return Map<String, Object> 包含uuid（用于标识验证码）和imageBase64
     */
    public Map<String, Object> sendCode() {
        // 生成验证码
        Map<String, Object> captchaResult = CaptchaImageUtil.generateCaptcha();
        String captchaCode = (String) captchaResult.get(FieldConstant.CODE);
        String imageBase64 = (String) captchaResult.get(FieldConstant.IMAGE);
        // 生成唯一的UUID作为验证码的key
        String uuid = UUID.randomUUID().toString();
        // 将验证码存入Redis，设置过期时间为5分钟
        objectRedisTemplate.opsForValue().set(uuid, captchaCode, 5, TimeUnit.MINUTES);
        // 返回结果（包含uuid和base64图片）
        Map<String, Object> result = new HashMap<>(2);
        result.put(FieldConstant.UUID, uuid);
        result.put(FieldConstant.IMAGE, imageBase64);
        return result;
    }

    /**
     * 查询用户列表
     *
     * @return
     */
    @Override
    public List<UserVO> listUser(String username, String name) {
        return userMapper.list(username, name);
    }

    /**
     * 新增用户
     *
     * @param userDTO
     */
    @Transactional
    @Override
    public void saveUser(UserDTO userDTO) {
        User user = BeanUtil.copyProperties(userDTO, User.class);
        user.setPassword(AuthUtil.encryptPassword("123456"));
        user.setCreateTime(LocalDateTime.now());
        userMapper.insert(user);
        userMapper.insertUserRole(user.getId(), 2L);
    }

    /**
     * 更新用户信息
     *
     * @param userDTO
     */
    @Override
    public void updateUser(UserDTO userDTO) {
        updateById(BeanUtil.copyProperties(userDTO, User.class));
    }

    /**
     * 删除用户
     *
     * @param id
     */
    @Transactional
    @Override
    public void removeUser(Long id) {
        //删除这个司机的签到信息
//        assessmentMapper.delete(new LambdaQueryWrapper<Assessment>().eq(Assessment::getDriverId, id));
        if (Objects.equals(id, BaseContext.getCurrentId())) {
            throw new BaseException("无法删除自己");
        }

        Long roleId = userMapper.selectRoleIdByUserId(id);
        if (roleId==1L) {
            throw new BaseException("无法删除管理员");
        }

        userMapper.deleteUserRole(id);
        removeById(id);
    }

    /**
     * 注册
     *
     * @param userRegisterDTO
     */
    @Transactional
    @Override
    public void register(UserRegisterDTO userRegisterDTO) {
        String password = userRegisterDTO.getPassword();
        if (!password.equals(userRegisterDTO.getRePassword())) {
            throw new RegisterException("两次密码不一致");
        }
        User user = User.builder()
                .username(userRegisterDTO.getUsername())
                .phoneNumber(userRegisterDTO.getPhoneNumber())
                .idCard(userRegisterDTO.getIdCard())
                .name(userRegisterDTO.getName())
                .password(AuthUtil.encryptPassword(password))
                .createTime(LocalDateTime.now()).build();
        userMapper.insert(user);
        userMapper.insertUserRole(user.getId(), 2L);
    }

    /**
     * 重置密码
     *
     * @param id
     */
    @Override
    public void reset(Long id) {
        User user = User.builder().id(id).password(AuthUtil.encryptPassword("123456")).build();
        updateById(user);
    }


    /**
     * 校验验证码
     *
     * @param uuid 唯一标识符
     * @param code 用户输入的验证码
     * @return boolean 验证码是否正确
     */
    private boolean verifyCaptcha(String uuid, String code) {
        // 从Redis获取验证码
        String storedCode = Objects.requireNonNull(objectRedisTemplate.opsForValue().get(uuid)).toString();
        if (storedCode == null || storedCode.isEmpty()) {
            return false; // 验证码不存在或已过期
        }
        // 比较用户输入的验证码与存储的验证码
        boolean isMatch = storedCode.equalsIgnoreCase(code);
        if (isMatch) {
            objectRedisTemplate.delete(uuid); // 删除已使用的验证码
        }
        return isMatch;
    }
}
